
package com.hlkj.pay.app.merchant.ext.impl.helipay.ext;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderQueryContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelRefundPayOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.helipay.HeliPayScenePayOrderExtPt;
import com.hlkj.pay.app.merchant.ext.impl.helipay.constant.HeliPayConstant;
import com.hlkj.pay.app.merchant.ext.impl.helipay.constant.HeliPayExtConstant;
import com.hlkj.pay.app.merchant.ext.impl.helipay.dto.HeliPayAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.helipay.dto.HeliPayConfig;
import com.hlkj.pay.app.merchant.ext.impl.helipay.dto.res.HeliPayOrderSubmitRes;
import com.hlkj.pay.app.merchant.ext.impl.helipay.handler.HeliPayMerchantCommonParamsHandle;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.util.MerchantUtils;
import com.hlkj.pay.vo.order.req.PayOrderCommonParamReq;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 条码支付，商户扫用户二维码收款
 * 
 * @author HlpayTeam
 * @date 2024/11/18 13:08
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = HeliPayExtConstant.H5)
public class HeliPayH5PayOrderExtPt extends HeliPaySceneCommonPayOrder implements HeliPayScenePayOrderExtPt {

    @Autowired
    private HeliPayMerchantCommonParamsHandle heliPayMerchantCommonParamsHandle;

    @Override
    public void submitChannelPayOrder(ChannelPayOrderContext channelPayOrderContext) {
        // 配置转换
        CommonResult<HeliPayConfig> commonResult = heliPayMerchantCommonParamsHandle.heliPayConfig(channelPayOrderContext.getProviderChannelConfigDO(),
                channelPayOrderContext.isTest());
        HeliPayConfig heliPayConfig = commonResult.getData();

        PayOrderDO payOrderDO = channelPayOrderContext.getPayOrderDO();
        HeliPayAppChannelParams heliPayAppChannelParams = heliPayAppChannelParams(channelPayOrderContext.getMerchantAppChannelDO());
        PayWayDO payWayDO = channelPayOrderContext.getPayWayDO();
        try {
            String payUrl = heliPayMerchantCommonParamsHandle.payUrl(channelPayOrderContext.isTest());
            LinkedHashMap<String, String> signFieldMap = new LinkedHashMap<>();
            Map<String, Object> noSignFieldMap = new HashMap<>();
            signFieldMap.put("P1_bizType", "AppPayH5WFT");
            signFieldMap.put("P2_orderId", payOrderDO.getPayOrderNo());
            signFieldMap.put("P3_customerNumber", heliPayAppChannelParams.getMerchantNo());
            signFieldMap.put("P4_orderAmount", MerchantUtils.bigDecimalToString2(payOrderDO.getAmount()));
            signFieldMap.put("P5_currency", "CNY");
            signFieldMap.put("P6_orderIp", payOrderDO.getClientIp());
            signFieldMap.put("P7_notifyUrl", channelPayOrderContext.getNotifyUrl());
            // signFieldMap.put("P8_appPayType", "WXPAY");
            PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByCode(payWayDO.getType());
            switch (payType) {
                case WECHAT:
                    signFieldMap.put("P8_appPayType", "WXPAY");
                    break;
                case ALIPAY:
                    signFieldMap.put("P8_appPayType", "ALIPAY");
                    break;
                case UNION_APY:
                    signFieldMap.put("P8_appPayType", "UNIONPAY");
                    break;
                case JDBT:
                    signFieldMap.put("P8_appPayType", "JDPAY");
                    break;
            }
            signFieldMap.put("P9_payType", "WAP");
            PayOrderCommonParamReq.Extra extra = JsonUtils.parseObject(payOrderDO.getExtra(), PayOrderCommonParamReq.Extra.class);
            if(StringUtils.hasText(extra.getAppName())){
                signFieldMap.put("P10_appName", extra.getAppName());
            }else {
                signFieldMap.put("P10_appName", "");
            }
            signFieldMap.put("P11_deviceInfo", "AND_WAP");
            // todo
            signFieldMap.put("P12_applicationId", "AND_WAP");
            signFieldMap.put("P13_goodsName", payOrderDO.getSubject());
            signFieldMap.put("P14_goodsDetail", "");
            signFieldMap.put("P15_desc", payOrderDO.getDescription());

            noSignFieldMap.put("successToUrl", channelPayOrderContext.getRedirectUrl());
            if (!CollectionUtils.isEmpty(channelPayOrderContext.getAccounts())) {
                noSignFieldMap.put("splitBillType", "FIXED_AMOUNT");
                noSignFieldMap.put("ruleJson", accountRuleJson(channelPayOrderContext.getAccounts()));
            }
            log.info("合利宝 H5支付 请求参数:{}", JsonUtils.toJsonString(signFieldMap));
            CommonResult<String> resultResult = heliPayMerchantCommonParamsHandle.heliPayOrderRequest(payUrl, heliPayConfig, signFieldMap, null);
            log.info("合利宝 H5支付 返回参数:{}", JsonUtils.toJsonString(resultResult));
            if (!resultResult.isSuccess()) {
                channelPayOrderContext.setRemark("合利宝H5支付请求失败,失败信息" + resultResult.getMsg());
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                return;
            }
            String response = resultResult.getData();
            HeliPayOrderSubmitRes heliPayOrderQueryRes = JsonUtils.parseObject(response, HeliPayOrderSubmitRes.class);

            if (HeliPayConstant.REQUEST_SUCCESS.equals(heliPayOrderQueryRes.getRt2_retCode())) {
                channelPayOrderContext.setPayDataType("data");
                channelPayOrderContext.setPayInfo(heliPayOrderQueryRes.getRt8_payInfo());
            }
            else {
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(heliPayOrderQueryRes.getRt3_retMsg())) {
                    channelPayOrderContext.setRemark(heliPayOrderQueryRes.getRt3_retMsg());
                }
                else {
                    channelPayOrderContext.setRemark("合利宝提交H5支付返回错误信息为空,错误码为:" + heliPayOrderQueryRes.getRt2_retCode());
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("合利宝提交H5支付请求失败 message:{}", e.getMessage(), e);
            channelPayOrderContext.setRemark("合利宝提交H5支付请求失败,失败信息" + e.getMessage());
            channelPayOrderContext.setProcessStatus(Boolean.FALSE);
            // channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.APPROVE_REFUSE);
        }
    }

    @Override
    public void queryChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void closeChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonCloseChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void queryChannelClosePayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelClosePayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void refundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public void queryRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonQueryRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public boolean refundApply(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        return true;
    }

    @Override
    public CommonResult<String> channelOrderCode(ChannelPayOrderContext channelPayOrderContext) {
        return CommonResult.success();
    }
}
